/***************************************************************
                       score.c
routines for the CpM table
routines for using a variable tolerance
some other ad hoc routines for returning matches.
The Sulston computation is in serial/score.c and shared/score.c
**************************************************************/
#include <stdio.h>
#include <malloc.h>
#include <float.h>
#include <math.h>
#include "clam.h"

/**************** Marker & Clones *****************/

#define FAST_SUL_ITERATIONS 3

#define graphQuery messQuery

void CpMdisplay(), ZautoCpM();
int  ZscoreCpM(struct tmpCz*, struct tmpCz*, struct tmpSz*);
BOOL ZboolCpM();
int Zcnt_shared_markers(struct tmpCz*, struct tmpCz*, struct tmpSz*);
void Read_unc(), set_Zunc(), ZbuildCpM();

#define VAR 0.001
float f_unc;
extern void scanClam(), ClamCtgDisplay2();
extern void ZclearHigh(), ZhighCin(), EvalCtgDisplay(), CBCtgDisplay();
extern int Zget_tol();
extern void ClamShare();
extern int NoPop;
extern int validDistribution;
extern float *distrib;
extern int loadCz();

static void Minus(), Plus();

#define MAX_UNC 20
static int U=1;
static struct {
   int	 len;
   float unc;
} Unc[MAX_UNC];

float Zunc;

/* there an almost duplicate of this in clam.h - don't know why sness did it */
static struct CpMtmp {
  int nm;
  double cut;
} CpMstore[MAX_CpM];

/***************************************************************
                        Pz_default()
called at beginnig of fpc_load
***************************************************************/
void Pz_default()
{
       defaultflag = DEFAULTFLAG;
       Proj.uncfile[0] = '\0';
       Proj.filterfile[0] = '\0';
       Proj.variable = FALSE;
       Proj.eq2 = 0;
       Proj.gel_len = 3300;
       Proj.avgbandsize=4096;
       Proj.genomesize=0;
       Proj.avginsertsize=0;
       Proj.mapname[0]='\0';
       Proj.automsg=TRUE;
       Proj.MaxClip = 4600;
       Proj.MinClip = 0;
       strcpy(Proj.label_abbrev,"Chr");

       Pz.tol = 7;
       Pz.burFlt = 0.10;
       Pz.fromendInt=15;   /* FromEnd for singles->ends */
       Pz.seq_fromendInt = 100;   /* FromEnd for singles->ends */
       Pz.mergeMatches = 2;   /* # of overlaps to merge contigs */
       Pz.diffInt=15; /* bad overlap */
       Pz.bestInt=10; /* best of for contig analysis */
       Pz.killInt = -1;
       Pz.logFlag=0;
       Pz.stdFlag=1;
       Pz.minVal=0;
       Pz.maxVal=INT_MAX;
       Pz.minBands = 0;
       Pz.DQstep = 1;
       Pz.DQnumq = 5;
       Pz.DQusePct = 0;
       Pz.seqFlag = 1;    /* always display seqeuence*/
       Pz.precompute = 0; /* precompute sulston scores */
       Pz.autoaddFlag = 0;
       Pz.adjust = 1;
       Pz.gap=0.2;            /* gap allowed in CB map alignment for HICF (check cb_assemble.c) */
       Pz.p_align=0.5;        /* amount alignment needed, otherwise, A clone */
       Pz.ctg=Pz.offset=0;
       Pz.ok_olap= 10;      /* overlap between ordered CBmaps */
       Pz.fp_class = AGAROSE;

       Bd.date.day = 1;
       Bd.date.month = 1;
       Bd.date.year = 70;
       Bd.date.minute = 0;
       Bd.date.hour = 0;
       Bd.useFlag = TRUE; /* CHG - CAS from 0 so always CBmap by default*/
       Bd.maxCpM=50;
       Bd.usePCR=TRUE;
       Bd.useYBP=FALSE;
       Bd.useREP=FALSE;

       Cp.useFlag=FALSE;
       Cp.maxCpM=50;
       Cp.autoFlag=TRUE;
       Cp.usePCR=TRUE;
       Cp.useYBP=FALSE;
       Cp.useREP=FALSE;

       Pz.cutFlt = 1.e-12; /* CHG - CAS 15May07 from 1.e-10 */
       CpM[0].nm = CpM[0].bd_nm = -1;

       Zadd=0;
       Zpq = NULL;
       Zset = NULL;
       n_Zpq = n_Zset = max_Zpq = max_Zset = 0;
       ZS = -1;
       LastCB=NoCB;
}
/***************************************************************
                        Pz_init()
called at end of fpc_load
***************************************************************/
void Pz_init()
{
char str1[2024];
int i;

if (Pz.tol == -1)
  Pz.tol = 7;
     if (Proj.uncfile[0]!='\0') Read_unc();
     else if (Proj.variable) set_Zunc();

     if (Proj.avgbandsize==0) Proj.avgbandsize=4096;
     if (Proj.gel_len<=0) Proj.gel_len=3300;
     if (Pz.burFlt<0.0) Pz.burFlt = 0.10;
     if (Pz.cutFlt<0.0) Pz.cutFlt = 1.e-12;
     if (Pz.fromendInt<0) Pz.fromendInt=15;   /* FromEnd end */
     if (Pz.diffInt<0) Pz.diffInt=15; /* bad overlap */
     if (Pz.bestInt<0) Pz.bestInt=5; /* best of for contig analysis */
     if (Pz.killInt<0) Pz.killInt= -1; /* -1 is max, kill all contig < this number */

     if(strlen(dirName)>0) sprintf(str1,"%s/Sizes",dirName);
     else sprintf(str1,"Sizes");
     Pz.useSz=0; /* cari 7apr */

     if (CpM[0].nm <= -1) {
       CpM[0].nm = 0;
       CpM[0].cut = Pz.cutFlt;
       for (i=1; i<MAX_CpM; i++) {
          CpM[i].nm = i;
          CpM[i].cut = CpM[i-1].cut * 10.0;
       }
     }
     if (CpM[0].bd_nm == -1) ZbuildCpM(0);
}
/**************************************************************
                        Zbcm
*************************************************************/
int Zbcm(int b1, int diff)
{
int unc, len;

    len = b1 - (diff >> 1);
    unc = Zget_tol(len);
    return (abs(diff) <= unc);
}
/**************************************************************
			Interpolate
****************************************************************/
int Zget_tol(int len)
{
float x, y=0, y1, y2, x1, x2;
int unc;
int i, j;

   if (!Proj.variable) return Pz.tol;

      if (U==1) {
          f_unc = Zunc * (float) len;
      }
      else if (len <= Unc[0].len) {
	  f_unc =  (((float) len) * Unc[0].unc);
      }
      else if (len >= Unc[U-1].len) {
	  f_unc = (((float) len) * Unc[U-1].unc);
      }
      else {
	 for (i=1, j= -1; i<U && j == -1; i++)
	    if (len >= Unc[i-1].len && len <= Unc[i].len) j=i;

	 y1 = Unc[j].unc;
	 y2 = Unc[j-1].unc;
	 x1 = (float) Unc[j].len;
	 x2 = (float) Unc[j-1].len;
	 x  = (float) len;
	 y = y1 + ((x - x1)/(x2 - x1)) * (y2 - y1);
	 f_unc = ((float) len * y);
     }
     unc = (int) f_unc + 0.5;
return unc;
}

/*********************************************************************
                    DEF: Zgetdiff
*******************************************************************/
void Zgetdiff()
{
int kbnd, k, l, idiff, lstart, i;

  for (i=0; i<NBANDS; i++) Sz.diff[i] = 100;

  Sz.total = Sz.match = 0;
  lstart = 0;
  for (i = k = 0; k < C1z.nbands; ++k)
  {
      kbnd = C1z.coords[k];
      for (l = lstart; l < C2z.nbands; ++l)
      {
	  idiff = kbnd - C2z.coords[l];
	  if (Ztol(kbnd, idiff))
	    {
	      lstart = l + 1;
	      break;
	    }
	  else if (idiff < 0)
	    {
              Sz.diff[Sz.match] = kbnd;
	      Sz.match++;
	      lstart = l;
	      break;
	    }
       }
   }
  return;
}

/****************************************************************************
                            Zfp_match(c1, c2)
Used by Search routine Fingerprint for clones.
****************************************************************************/
int Zfp_match(int c1, int c2)
{
  Pz_init(); scanClam();
  if (c1==c2) return 0;
  if (!loadCzfast(&C1z, c1)) {
      printf("Cannot eval clone1 %s",arrp(acedata, c1, CLONE)->clone);
      return 1;
  }
  if (!loadCzfast(&C2z, c2)) {
      printf("Cannot eval clone2 %s",arrp(acedata, c2, CLONE)->clone);
      return 1;
  }
  Zsulston(&C1z,&C2z,&Sz);
  if (Sz.prob <= Pz.cutFlt) return 1;
  return 0;
}
/***************************************************************
                        clear_Zunc()
***************************************************************/
void clear_Zunc()
{
    U=1;
    Zunc = VAR * (float) Pz.tol;
    if (Proj.variable)
      fprintf(stdout,"Tolerance is %f (0.001 * tolerance)\n",
         (0.001 * (float) Pz.tol));
    else
      fprintf(stdout,"Tolerance is %d \n", Pz.tol);
}
/***************************************************************
                        set_Zunc()
***************************************************************/
void set_Zunc()
{
static int last=0;

    if (!Proj.variable) return;
    U=1;
    Zunc = VAR * (float) Pz.tol;
    if (last!=Pz.tol)
        fprintf(stderr,"Tolerance is %f (0.001 * tolerance)\n",
         (0.001 * (float) Pz.tol));
    last = Pz.tol;
}
/***********************************************************************8
		       Read_uncF
*****************************************************************************/
void Read_unc()
{
FILE *in, *sopen();
int  i,j;
char buf[500];
int  len;
float unc;

   U=1;
   if (Proj.uncfile[0] == '\0') goto done;

   in = fopen(Proj.uncfile,"r");
   if (in==NULL) {
       sprintf(buf,"*** Cannot open uncertainity file %s", Proj.uncfile);
       displaymess(buf);
       return;
   }
   U=0;
   while (fgets(buf,500,in)!=0) {
       if (U==MAX_UNC) {
	   sprintf(buf,
	   "*** Number of uncertainity values exceeds limit (%d)",MAX_UNC);
           displaymess(buf);
	   return;
       }
       if (buf[0]!='\n' && buf[0] != '#') {
	  sscanf(buf,"%d %f", &Unc[U].len, &Unc[U].unc);
	  U++;
       }
   }
   fclose(in);
   for (i=0; i<U-1; i++)
     for (j=i+1; j<U; j++)
     {
	 if (Unc[i].len > Unc[j].len) {
	    len = Unc[i].len;
	    unc = Unc[i].unc;
	    Unc[i].len = Unc[j].len;
	    Unc[i].unc = Unc[j].unc;
	    Unc[j].len = len;
	    Unc[j].unc = unc;
	 }
     }
done:;
   Proj.gel_len= (Proj.variable) ? 7000 : Proj.gel_len;
   if (U > 1) {
     Pz.tol=0;
     printf("Read %d tolerance values from file %s\n",U, Proj.uncfile);
   }
   else if (Pz.tol==0) Pz.tol=Pz.tol=7;
   NoPop=1; ClamCtgDisplay2(); EvalCtgDisplay(); CBCtgDisplay(); NoPop=0;
return;
}
/************************************************************/
/************************************************************
                DEF: CpMdisplay routines
**********************************************************/
Graph gCpM;
static int traceArc, autoArc, usePCRArc, useYBPArc, useREPArc, minBox, maxBox, MpCBox, CpMBox;
static char MpCText[10], minText[10], maxText[10];
static struct contig *stepCpM;
char CpMText[100];
#define Show {if (graphActivate(gCpM)){graphPop(); graphRedraw();}}

/************************************************
         DEF: do_step
*************************************************/
static void do_step(int index)
{
static int ctg=0, cnt=0, cntp=0;
struct contig *p, *q;
CLONE clone;
int mk, o;
char t1[10], t2[10];

  if (currentctg<=0 || root==NULL) return;
  ZclearHigh();
  if (currentctg!=ctg) stepCpM = root;
  else if (stepCpM==NULL) stepCpM = root;
  ctg = currentctg;
  if (stepCpM==root) cnt=0;

  for (p=stepCpM; p!=NULL; p = p->new)
  {
      if (graphInterruptCalled()) {
          printf("User Interrupt - pre-mature termination of CpMStep\n");
          return;
      }
     clone = arr(acedata, p->next, CLONE);
     if (clone.fp == NULL)  continue;
     if (showburied==1 && clone.match[0]!=' ') continue; /* V2.2 */
     if (showburied==2 && clone.mattype == PSEUDO) continue; /* V2.2 */
     if (!loadCz(&C1z, p->next)) continue;
     cntp=0;

     for (q=root; q!=NULL; q = q->new)
     {
         if (!loadCz(&C2z, q->next)) continue;
         if (showburied==1 && C2z.parent[0]!=' ') continue;
         if (showburied==2 && strcmp(C2z.btype, "pseudo")==0) continue;
         if (strcmp(C1z.clone, C2z.clone)==0) continue;
         Zsulston(&C1z,&C2z,&Sz);
         if (Sz.prob <= CpM[index].cut && Sz.prob > CpM[index-1].cut) {
             mk = Zcnt_shared_markers(&C1z,&C2z,&Sz);
             if (mk >= CpM[index].nm) {
                o = arrp(acedata, C1z.cin, CLONE)->oldctg;
                if (o > OLDCTG_MARK) sprintf(t1, "%d CpM", o - OLDCTG_MARK);
                else  sprintf(t1, "%d", o);
                o = arrp(acedata, C2z.cin, CLONE)->oldctg;
                if (o > OLDCTG_MARK) sprintf(t2, "%d CpM", o - OLDCTG_MARK);
                else  sprintf(t2, "%d", o);
                sprintf(ZBuf,"%12s %12s   Markers %-3d  %.0e (%s, %s)\n",
                   C1z.clone, C2z.clone, mk, Sz.prob, t1, t2); Outlog;
                ZhighCin(CLAM, C2z.cin);
                if (p->box==0) {
                   centre_pos = arrp(acedata,p->next, CLONE)->x;
                   ctgdisplay(currentctg);
                }
                cntp++;
             }
         }
     }
     stepCpM = p->new;
     if (cntp>0) {
        cnt++;
        ZhighCin(CLAM_CLONE, C1z.cin);
        sprintf(CpMText,"Step%d #%d %s %d",index,cnt, C1z.clone, cntp); Show;
        return;
     }
  }
  stepCpM=NULL;
  printf("Stepped through %d Step%d\n", cnt, index);
  sprintf(CpMText,"Stepped through %d step%d",cnt, index); Show;
}
static void step1() { do_step(1); }
static void step2() { do_step(2); }
static void step3() { do_step(3); }
/**************************************************************
            DE: ZboolCpM
All clam routines call this for scoreing (Zsulston or Zmott must be called
before this).
**************************************************************/
BOOL ZboolCpM()
{
int  exp;

   exp = ZscoreCpM(&C1z,&C2z,&Sz);
   if (exp > 0)
   {
      return TRUE;
   }

   return FALSE;
}
/*************************************************************************
              saving and loading
*************************************************************************/
/***************************************************
         DEF: ZsaveCpM - called in fpc_save.c
***************************************************/
void ZsaveCpM(char *msg) /* fpc_load looks for // CpM */
{
char tmp[30];
  if (Cp.useFlag==0) strcpy(tmp,"Off");
  else  strcpy(tmp,"On");
  sprintf(msg,"// CpM %s %d %d %d %d TBL %d %.0e %d %.0e %d %.0e\n",
        tmp, Cp.maxCpM, Cp.usePCR, Cp.useYBP, Cp.useREP,
        CpM[1].nm, CpM[1].cut,
        CpM[2].nm, CpM[2].cut, CpM[3].nm, CpM[3].cut);
}
/***************************************************
         DEF: ZloadCpM - called in fpc_load.c
***************************************************/
void ZloadCpM(char *msg)
{
char tmp[30];

  sscanf(msg,"// CpM %s %d %d %d %d TBL %d %lf %d %lf %d %lf\n",
     tmp, &(Cp.maxCpM), (int*) &(Cp.usePCR), (int*) &(Cp.useYBP), (int*) &(Cp.useREP),
     &(CpM[1].nm), &(CpM[1].cut), &(CpM[2].nm), &(CpM[2].cut),
     &(CpM[3].nm), &(CpM[3].cut));
 CpM[0].nm = 0;
 CpM[0].cut = Pz.cutFlt;
 if (strcmp(tmp,"Off")==0) Cp.useFlag=0;
 else Cp.useFlag=1;
}
/***************************************************
         DEF: ZsaveBuild - called in fpc_save.c
***************************************************/
void ZsaveBuild(char *msg) /* fpc_load looks for // Build */
{
char tmp[30], tmp2[100];

  if (Bd.useFlag==0) strcpy(tmp,"Off");
  else  strcpy(tmp,"On");
  sprintf(tmp2,"%s %d %d %d %d TBL %d %.0e %d %.0e %d %.0e ",
        tmp, Cp.maxCpM, Cp.usePCR, Cp.useYBP, Cp.useREP,
        CpM[1].bd_nm, CpM[1].bd_cut,
        CpM[2].bd_nm, CpM[2].bd_cut, CpM[3].bd_nm, CpM[3].bd_cut);
  sprintf(msg, "// Build %d/%d/%d %d:%d Cut %.0e %s\n",
        Bd.date.day, Bd.date.month, Bd.date.year, Bd.date.hour,
        Bd.date.minute, Bd.cutoff, tmp2);
}
/***************************************************
         DEF: ZloadCpM - called in fpc_load.c
***************************************************/
void ZloadBuild(char *msg)
{
char tmp[30];

    sscanf(msg,"// Build %d/%d/%d %d:%d Cut %lf %s %d %d %d %d TBL %d %lf %d %lf %d %lf\n",
       &Bd.date.day, &Bd.date.month, &Bd.date.year, &Bd.date.hour, &Bd.date.minute,
       &Bd.cutoff, tmp, &Bd.maxCpM, (int*) &Bd.usePCR, (int*) &Bd.useYBP,
       (int*) &(Bd.useREP), &(CpM[1].bd_nm), &(CpM[1].bd_cut),
       &(CpM[2].bd_nm), &(CpM[2].bd_cut), &(CpM[3].bd_nm), &(CpM[3].bd_cut));
    CpM[0].bd_cut = Bd.cutoff;
    CpM[0].bd_nm = 0;

 if (strcmp(tmp,"Off")==0) Bd.useFlag=0;
 else Bd.useFlag=1;
}
/********************************************************************
                   outputting stats
********************************************************************/
/*********************************************
         DEF: print_params()
Called before incremental build
*********************************************/
int init_CpM(int print)
{
     /* cari 9 aug 4 - can get bad values in table */
  if (Cp.useFlag==1)
     if (CpM[0].cut==0.0 || CpM[1].cut == 0.0 ||
             CpM[2].cut == 0.0 || CpM[3].cut==0.0) {
        printf( "Cutoff %.0e CpM (%d %.0e)(%d %.0e)(%d %.0e)\n",
          CpM[0].cut, CpM[1].nm, CpM[1].cut,
          CpM[2].nm, CpM[2].cut, CpM[3].nm, CpM[3].cut);
        if (messQuery("CpM table has some zero values. Would you like to abort?")) {
              return 0;
        }
     }
  CpMTbl[0].cnt = CpMTbl[1].cnt = CpMTbl[2].cnt = CpMTbl[3].cnt = 0;
  if (!print) return 1;

  if (Cp.useFlag==1) {
    sprintf(ZBuf,
"Cutoff %.0e CpM (%d %.0e)(%d %.0e)(%d %.0e) Ignore %d. ePCR %d. YBP %d. REP %d.\n",
        CpM[0].cut, CpM[1].nm, CpM[1].cut,
        CpM[2].nm, CpM[2].cut, CpM[3].nm, CpM[3].cut,
        Cp.maxCpM, Cp.usePCR, Cp.useYBP, Cp.useREP);
  }
  return 1;
}
/************************************************************
             special purpose
***********************************************************/
/*********************************************
         DEF: ZbuildCpM
*********************************************/
void ZbuildCpM()
{
int i;
  for (i=0; i<MAX_CpM; i++) {
      CpM[i].bd_nm = CpM[i].nm;
      CpM[i].bd_cut = CpM[i].cut;
  }
  Bd.cutoff = Pz.cutFlt;
  Bd.useFlag = Cp.useFlag;
  Bd.maxCpM = Cp.maxCpM;
  Bd.usePCR = Cp.usePCR;
  Bd.useYBP = Cp.useYBP;
  Bd.useREP = Cp.useREP;
}
/*********************************************
         DEF: ZibcCpM
*********************************************/
int ZibcCpM()
{
int i;
int ok=1;
char tmp[500];

  if (!Bd.useFlag && !Cp.useFlag) {
     if (Pz.cutFlt != Bd.cutoff) {
         sprintf(tmp,"Use cutoff %.0e (Yes) or\n Last Cutoff %.0e (No)", 
                        Pz.cutFlt, Bd.cutoff);
         if (messQuery(tmp)) 
             Bd.cutoff = CpM[0].bd_cut = Pz.cutFlt; /* new values */
         else Pz.cutFlt = Bd.cutoff;
         NoPop=1;
           ClamCtgDisplay2();
           if (graphExists(gCpM)) CpMdisplay();
         NoPop=0;
     }
     return 1;
  }
  if (Cp.useFlag != Bd.useFlag) ok=0;
  CpM[0].bd_cut = Bd.cutoff;
  for (i=0; i<MAX_CpM; i++) {
      if (CpM[i].bd_nm != CpM[i].nm) ok=0;
      if (CpM[i].bd_cut != CpM[i].cut) ok=0;
  }
  if (Cp.maxCpM != Bd.maxCpM) ok=0;
  if (Cp.usePCR != Bd.usePCR) ok=0;
  if (Cp.useYBP != Bd.useYBP) ok=0;
  if (Cp.useREP != Bd.useREP) ok=0;
  if (!ok) {
     CpMdisplay();
     if (!messQuery("Use Last Build CpM table?")) {
        if (!messQuery("Use Current CpM table?")) return 0;
        ZbuildCpM(); /* new values */
        NoPop=1; ClamCtgDisplay2(); NoPop=0;
     }
     else  {
        for (i=0; i<MAX_CpM; i++) {
            CpM[i].nm = CpM[i].bd_nm;
            CpM[i].cut = CpM[i].bd_cut;
        }
        Cp.useFlag = Bd.useFlag;
        Cp.maxCpM = Bd.maxCpM;
        Cp.usePCR = Bd.usePCR;
        Cp.useYBP = Bd.useYBP;
        Cp.useREP = Bd.useREP;
        if (graphExists(gCpM)) {
            NoPop=1; CpMdisplay(); NoPop=0;
        }
        if (Pz.cutFlt != Bd.cutoff) {
            Pz.cutFlt = Bd.cutoff;
            ClamShare(0);
        }

     }
     CpMdisplay();
  }
  return 1;
}
/**************************************************
           DEF: ZstoreCpM
***************************************************/
void ZstoreCpM()
{
int i;
  for (i=1; i<MAX_CpM; i++) {
      CpMstore[i].nm = CpM[i].nm;
      CpMstore[i].cut = CpM[i].cut;
  }
}
/**************************************************
           DEF: ZrestoreCpM
***************************************************/
void ZrestoreCpM()
{
int i;
  CpM[0].cut = Pz.cutFlt;
  for (i=1; i<MAX_CpM; i++) {
      CpM[i].nm = CpMstore[i].nm;
      CpM[i].cut = CpMstore[i].cut;
  }
}

/***************************************************
           DEF: ZautoCpM
***************************************************/
void ZautoCpM(int p)
{
int i;
char str1[20], str2[20];
int diff, man1, man2, exp1, exp2;

   sprintf(str1, "%.0e", Pz.cutFlt);
   sprintf(str2, "%.0e", CpM[0].cut);

   CpM[0].nm = 0;
   CpM[0].cut = Pz.cutFlt;
   if (Cp.autoFlag) {
      sscanf(str1, "%de-%d",&man1, &exp1);
      sscanf(str2, "%de-%d",&man2, &exp2);
      diff = exp1 - exp2;

      if (diff < 0) for (i=0; i<abs(diff); i++) Plus();
      else for (i=0; i<diff; i++) Minus();
   }
   if (p && Cp.useFlag) printf(
  "Cutoff %.0e CpM (%d %.0e)(%d %.0e)(%d %.0e)\n",
        CpM[0].cut, CpM[1].nm, CpM[1].cut,
        CpM[2].nm, CpM[2].cut, CpM[3].nm, CpM[3].cut);
   if (graphExists(gCpM)) {
       NoPop=1; CpMdisplay(); NoPop=0;
   }
}
/*******************************************************
              other variable window stuff
*******************************************************/
/*********************************************
         DEF: quitCpM
*********************************************/
void quitCpM()
{
   if (graphActivate(gCpM)) {
       stepCpM=NULL;
       graphDestroy();
   }
}
/*********************************************
         DEF: scanCpM
*********************************************/
static void scanCpM(char *tmp)
{
int i;
  CpM[0].nm=0;
  CpM[0].cut = Pz.cutFlt;
  for (i=1; i<MAX_CpM; i++) {
      sscanf(CpMTbl[i].nmText,"%d",&CpM[i].nm);
      sscanf(CpMTbl[i].cutText,"%lf",&CpM[i].cut);
  }
  for (i=1; i<MAX_CpM; i++) {
      if (CpM[i].nm < CpM[i-1].nm) {
         printf("Incorrect number of markers %d for entry %d. Set to %d.\n",
           CpM[i].nm, i, i);
         CpM[i].nm = i;
         CpMdisplay();
      }
      if (CpM[i].cut <  CpM[i-1].cut) {
         printf("Incorrect cutoff %.0e for entry %d. Set to %.0e.\n",
           CpM[i].cut, i, CpM[i-1].cut*10.0);
         CpM[i].cut = CpM[i-1].cut*10.0;
         CpMdisplay();
      }
  }
  sscanf(MpCText,"%d",&Cp.maxCpM);
  if (Cp.maxCpM < 0) Cp.maxCpM = 0;
  sscanf(minText,"%d",&Pz.minVal);
  sscanf(maxText,"%d",&Pz.maxVal);
  if (Pz.maxVal < 1000) {
     printf("Max value %d to low, set to 1000\n", Pz.maxVal);
     Pz.maxVal = 1000;
     CpMdisplay();
  }
  if (Pz.minVal < 0 || Pz.minVal > Pz.maxVal) Pz.minVal = 0;
}
/*********************************************
         DEF: pickCpM
*********************************************/
static void pickCpM(int box,double x,double y)
{
int i;

  if (box == autoArc) {
    Cp.autoFlag = (!Cp.autoFlag);
    CpMdisplay();
  }
  else if (box == traceArc) {
    Proj.automsg = (!Proj.automsg);
    CpMdisplay();
  }
  else if (box == usePCRArc) {
    Cp.usePCR = (!Cp.usePCR);
    CpMdisplay();
  }
  else if (box == useYBPArc) {
    Cp.useYBP = (!Cp.useYBP);
    CpMdisplay();
  }
  else if (box == useREPArc) {
    Cp.useREP = (!Cp.useREP);
    CpMdisplay();
  }
  else if (box == MpCBox) {
     MpCBox = graphTextEntry(MpCText,8,0,0,NULL);
     graphRedraw();
  }
  else if (box == minBox) {
     minBox = graphTextEntry(minText,8,0,0,NULL);
     graphRedraw();
  }
  else if (box == maxBox) {
     maxBox = graphTextEntry(maxText,8,0,0,NULL);
     graphRedraw();
  }
  else {
    if (Cp.useFlag==0) {
       graphMessage("Use CpM must be on to change values in the tables.");
       return;
    }
    for (i=1; i<MAX_CpM; i++)
       if (box == CpMTbl[i].nmBox) {
          CpMTbl[i].nmBox = graphTextEntry(CpMTbl[i].nmText,8,0,0,NULL);
          graphRedraw();
          return;
       }
    for (i=1; i<MAX_CpM; i++)
       if (box == CpMTbl[i].cutBox) {
           CpMTbl[i].cutBox = graphTextEntry(CpMTbl[i].cutText,8,0,0,NULL);
           graphRedraw();
           return;
       }
  }
}
/*************************************************
           DEF: ZsetCpM
**************************************************/
void ZsetCpM()
{
int i;
   if (CpM[1].cut <= Pz.cutFlt) {
       if (Cp.useFlag)
         printf("Adjusting CpM values - please check\n");
       CpM[0].cut = Pz.cutFlt;
       for (i=1; i<MAX_CpM; i++) {
          CpM[i].cut = CpM[i-1].cut * 10.0;
          CpM[i].nm = i; /* CAS 2-2-3 */
       }
   }
}
/***************************************************
           DEF: Plus
***************************************************/
static void Plus()
{
int i;
   for (i=1; i<MAX_CpM; i++)
         CpM[i].cut = CpM[i].cut * 10.0;

   if (graphExists(gCpM)) {
       NoPop=1; CpMdisplay(); NoPop=0;
   }
}
/***************************************************
           DEF: Minus
***************************************************/
static void Minus()
{
int i;
   for (i=1; i<MAX_CpM; i++)
       CpM[i].cut = CpM[i].cut / 10.0;

   if (graphExists(gCpM)) {
       NoPop=1; CpMdisplay(); NoPop=0;
   }
}

/*****************************************************
          DEF CpM window
*****************************************************/
void CpMdisplay()
{
static MENUOPT amenu[] = { { quitCpM, "Close"},
    { graphPrint,"Print Screen"},
    {0, 0 } };
float row=1.0, col, col1=4.0, col2=5.0, col3=11.0, col4=23.0, col5=33.0;
int i;
char tmp[100];

  if(graphActivate(gCpM)){
    graphClear();
    if (!NoPop) graphPop();
  }
  else{                       /* pos x, y; width, leng */
    gCpM = graphCreate (TEXT_FIT,"CpM Table",.2,.2,.37,.38);
    graphRegister (PICK, pickCpM) ;
  }
  graphMenu(amenu);

  CpMBox = graphBoxStart();
  graphTextPtr(CpMText,1.0,row,42);
  strcpy(CpMText, "      CpM (Cutoff plus Markers)");
  graphBoxEnd();
  graphBoxDraw(CpMBox,BLACK,CYAN);
  row += 2.0;
  col=3.0;
  autoArc = graphBoxStart();
      graphArc(col, row+0.5, 0.7, 0, 360);
      if (Cp.autoFlag) graphFillArc(col, row+0.5, 0.4, 0, 360);
      graphBoxEnd();
      graphBoxDraw(autoArc, BLACK, TRANSPARENT);
  graphText("Auto Adjust",col+1,row);
  col=18.0;
  graphText("CpM Cutoff:",col,row);
  col+=12.0;
  graphButton("+1",Plus,col,row);
  col+=4.0;
  graphButton("-1",Minus,col,row);

  row+=2.0;
  graphText("  Current CpM      Last Build",col1,row);
  row+=1.0;
  graphText("Markers  Cutoff",col1,row);
  if (currentctg > 0) {
     sprintf(tmp, "with ctg");
     graphText(tmp,col5,row);
  }
  row+=1.5;
  sprintf(tmp, ">=0    < %.0e",Pz.cutFlt);
  graphText(tmp,col1,row);

  sprintf(tmp, " 0 %.0e",CpM[0].bd_cut);
  graphText(tmp,col4,row);

  row+=1.5;
  for (i=1; i<MAX_CpM; i++) {
      if (Cp.useFlag) {
        sprintf(CpMTbl[i].nmText, "%d", CpM[i].nm);
        sprintf(CpMTbl[i].cutText, "%.0e", CpM[i].cut);
      }
      else {
        sprintf(CpMTbl[i].nmText, "-");
        sprintf(CpMTbl[i].cutText, "-");
      }

      graphText(">=",col1,row);
      CpMTbl[i].nmBox = graphTextEntry(CpMTbl[i].nmText,3,col2,row,scanCpM);

      graphText("<",col3,row);
      CpMTbl[i].cutBox = graphTextEntry(CpMTbl[i].cutText,6,col3+2.0,row,scanCpM);

      if (currentctg > 0 && Cp.useFlag) {
        sprintf(tmp, "Step%d",CpM[i].nm);
        if (i==1) graphButton(tmp,step1,col5,row);
        else if (i==2) graphButton(tmp,step2,col5,row);
        else if (i==3) graphButton(tmp,step3,col5,row);
      }
      if (Bd.useFlag) {
        sprintf(tmp, "%2d %.0e",CpM[i].bd_nm, CpM[i].bd_cut);
        graphText(tmp,col4,row);
      }
      else {
        graphText(" -  -",col4,row);
      }
      row+=1.5;
  }
  row+=0.5;
  col = col1;
  usePCRArc = graphBoxStart();
      graphArc(col, row+0.5, 0.7, 0, 360);
      if (Cp.usePCR) graphFillArc(col, row+0.5, 0.4, 0, 360);
      graphBoxEnd();
      graphBoxDraw(usePCRArc, BLACK, TRANSPARENT);
  graphText("Use ePCR",col+1,row);
  if (Bd.useFlag) {
    if (Bd.usePCR) graphText("Use ePCR",col4+1,row);
    else graphText("No  ePCR",col4+1,row);
  }
  row+=1.5;
  useYBPArc = graphBoxStart();
      graphArc(col, row+0.5, 0.7, 0, 360);
      if (Cp.useYBP) graphFillArc(col, row+0.5, 0.4, 0, 360);
      graphBoxEnd();
      graphBoxDraw(useYBPArc, BLACK, TRANSPARENT);
  graphText("Use YBP(ac)",col+1,row);
  if (Bd.useFlag) {
    if (Bd.useYBP) graphText("Use YBP(ac)",col4+1,row);
    else graphText("No  YBP(ac)",col4+1,row);
  }
  row+=1.5;
  useREPArc = graphBoxStart();
      graphArc(col, row+0.5, 0.7, 0, 360);
      if (Cp.useREP) graphFillArc(col, row+0.5, 0.4, 0, 360);
      graphBoxEnd();
      graphBoxDraw(useREPArc, BLACK, TRANSPARENT);
  graphText("Use REP",col+1,row);
  if (Bd.useFlag) {
    if (Bd.useREP) graphText("Use REP",col4+1,row);
    else graphText("No  REP",col4+1,row);
  }
  row+=1.5;
  col = 2.0;
  graphText("Ignore Markers in more than",col,row);
  sprintf(MpCText, "%d", Cp.maxCpM);
  MpCBox = graphTextEntry(MpCText,4,col+27,row,scanCpM);
  graphText("clones",col+31, row);
  row+=2.0;
  graphButton("Close",quitCpM,2.0,row);
/************************************/
  col = 2.0;
  row+=2.0;
  if (Proj.variable) graphText("Sizes: ",col,row);
  else graphText("Rates: ",col,row);
  col += 7.0;
  graphText("Min ",col,row);
  col += 4.0;
  sprintf(minText, "%d", Pz.minVal);
  minBox = graphTextEntry(minText,6,col,row,scanCpM);
  col += 9.0;
  graphText("Max ",col,row);
  col += 4.0;
  sprintf(maxText, "%d", Pz.maxVal);
  maxBox = graphTextEntry(maxText,6,col,row,scanCpM);
  graphRedraw();
}
